package org.catspaw.cherubim.security.ss3;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.TreeSet;
import java.util.Map.Entry;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.method.AbstractFallbackMethodSecurityMetadataSource;

import org.catspaw.cherubim.matcher.Matcher;

/**
 * 从数据库获取被访问的资源所需要的权限标识符 这里只处理Method（方法）资源
 * @author 孙宁振
 */
public class AspectjBasedSecurityMetadataSource extends
		AbstractFallbackMethodSecurityMetadataSource {

	private Matcher<String, Method>								methodMatcher;
	private Matcher<String, Class<?>>								classMatcher;
	private LinkedHashMap<String, Collection<ConfigAttribute>>	methodMap;
	private Collection<ConfigAttribute>							allConfigAttribute;

	public AspectjBasedSecurityMetadataSource(
			Matcher<String, Method> methodMatcher,
			LinkedHashMap<String, Collection<ConfigAttribute>> methodMap) {
		this(methodMatcher, null, methodMap);
	}

	public AspectjBasedSecurityMetadataSource(
			Matcher<String, Method> methodMatcher,
			Matcher<String, Class<?>> classMatcher,
			LinkedHashMap<String, Collection<ConfigAttribute>> methodMap) {
		this.methodMatcher = methodMatcher;
		this.classMatcher = classMatcher;
		this.methodMap = methodMap;
		allConfigAttribute = extractAllConfigAttribute(methodMap);
	}

	protected Collection<ConfigAttribute> extractAllConfigAttribute(
			LinkedHashMap<String, Collection<ConfigAttribute>> methodMap) {
		Collection<ConfigAttribute> all = new TreeSet<ConfigAttribute>(
				new Comparator<ConfigAttribute>() {

					public int compare(ConfigAttribute a1, ConfigAttribute a2) {
						return a1.getAttribute().compareTo(a2.getAttribute());
					}
				});
		for (Iterator<Collection<ConfigAttribute>> iterator = getMethodMap()
				.values().iterator(); iterator.hasNext();) {
			all.addAll(iterator.next());
		}
		return all;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return allConfigAttribute;
	}

	protected Collection<ConfigAttribute> findAttributes(Method method,
			Class<?> targetClass) {
		Set<Entry<String, Collection<ConfigAttribute>>> set = getMethodMap()
				.entrySet();
		for (Entry<String, Collection<ConfigAttribute>> entry : set) {
			String pattern = entry.getKey();
			boolean matched = getMethodMatcher().match(pattern, method);
			if (matched) {
				return entry.getValue();
			}
		}
		return null;
	}

	protected Collection<ConfigAttribute> findAttributes(Class<?> clazz) {
		Set<Entry<String, Collection<ConfigAttribute>>> set = getMethodMap()
				.entrySet();
		for (Entry<String, Collection<ConfigAttribute>> entry : set) {
			String pattern = entry.getKey();
			boolean matched = getClassMatcher().match(pattern, clazz);
			if (matched) {
				return entry.getValue();
			}
		}
		return null;
	}

	public LinkedHashMap<String, Collection<ConfigAttribute>> getMethodMap() {
		return methodMap;
	}

	public Matcher<String, Method> getMethodMatcher() {
		return methodMatcher;
	}

	public Matcher<String, Class<?>> getClassMatcher() {
		return classMatcher;
	}
}
